﻿using System;
using System.Linq;
using CID.Domain.Development;
using CID.Domain.Infrastructure;
using CID.Domain.Operations;
using CID.Execution.Agent.Tests.Support;
using CID.Execution.Support.Information;
using CID.Execution.Support.Scripting;
using CID.Execution.Support.TemplateHandling;
using NUnit.Framework;
using Rhino.Mocks;

namespace CID.Execution.Agent.Tests
{
    [TestFixture]
    class DeactivationScriptExecuterTests : BaseAgentTests
    {
        private const string CustomParameterName = "The Parameter Name";
        private const string CustomParameterValue = "SomeValue";

        private DeactivationScriptExecuter scriptExecuter;
        private LocationDeactivationScript script;
        private DeactivationScriptStep scriptStep;

        public override void SetUp()
        {
            base.SetUp();

            var location = GenerateNamedEntityStub<ILocation>();
            var release = GenerateNamedEntityStub<IRelease>();
            var component = GenerateNamedEntityStub<IComponent>();
            var templateType = GenerateNamedEntityStub<ITemplateType>();
            var template = GenerateNamedEntityStub<ITemplate>();
            template.Stub(x => x.Type).Return(templateType);

            scriptStep = new DeactivationScriptStep();
            scriptStep.Component = new ComponentInfo(component);
            scriptStep.Template = new TemplateInfo(template);
            scriptStep.ParameterValues = new ParameterValueInfo[] { ParameterValueInfo.CreateAdditionalParameterValue(CustomParameterName, CustomParameterValue) };
            script = new LocationDeactivationScript(Guid.NewGuid(), release, location, new DeactivationScriptStep[] { scriptStep });
            scriptExecuter = new DeactivationScriptExecuter(script);

            ControllerServiceProxyStub.ClearFlags();
            TemplateHandlerStub.ClearLists();
            TemplateHandlerFactory.Instance.RegisterTemplateHandlerType(scriptStep.Template.Type.Name, typeof(TemplateHandlerStub));
        }

        public override void TearDown()
        {
            TemplateHandlerFactory.Instance.UnregisterTemplateHandlerType(scriptStep.Template.Type.Name);
            base.TearDown();
        }

        #region ExecuteStep
        [Test]
        public void ExecuteStep_CustomTemplateHandlerRegistered_ShouldEndSuccessfully()
        {
            scriptExecuter.Execute();

            CollectionAssert.AreEquivalent(scriptStep.ParameterValues, TemplateHandlerStub.ParameterValues);
            CollectionAssert.AreEquivalent(new String[] { Parameter.ReservedNames.ReleaseName, Parameter.ReservedNames.ComponentName }, TemplateHandlerStub.AdditionalParameterValues.Select(x => x.ParameterName));
            Assert.IsTrue(ControllerServiceProxyStub.NotifyDeactivationCompletedCalled);
            Assert.IsFalse(ControllerServiceProxyStub.NotifyDeactivationCompletedWithErrors);
            Assert.IsFalse(ControllerServiceProxyStub.NotifyActivationCompletedCalled);
            Assert.IsFalse(ControllerServiceProxyStub.NotifyDeploymentCompletedCalled);
        }

        [Test]
        public void ExecuteStep_CustomTemplateHandlerNotRegistered_ShouldEndWithErrors()
        {
            TemplateHandlerFactory.Instance.UnregisterTemplateHandlerType(scriptStep.Template.Type.Name);

            scriptExecuter.Execute();

            Assert.IsTrue(ControllerServiceProxyStub.NotifyDeactivationCompletedCalled);
            Assert.IsTrue(ControllerServiceProxyStub.NotifyDeactivationCompletedWithErrors);
            Assert.IsFalse(ControllerServiceProxyStub.NotifyActivationCompletedCalled);
            Assert.IsFalse(ControllerServiceProxyStub.NotifyDeploymentCompletedCalled);
        }
        #endregion

        #region OnExecutionEnded
        [Test]
        public void FailCallToController_ShouldSucceedAndLog()
        {
            ControllerServiceProxyStub.FailOnCall = true;

            scriptExecuter.Execute();

            Assert.IsFalse(ControllerServiceProxyStub.NotifyDeactivationCompletedCalled);
        }
        #endregion
    }
}
